package com.wn.handler;

import com.wn.service.UserService;
import com.wn.utils.LogUtils;
import sun.rmi.runtime.NewThreadAction;
import sun.util.xml.PlatformXmlPropertiesProvider;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @author yellow Docter
 * @date 2022 -07-07
 * @desc
 *   使用jdk 的动态代理 创建一个代理对象 UserServiceImpl
 *   我在动态代理对象中 进入 切入操作 ,对业务方法添加日志
 *
 *   01 需要把 业务代码的接口传入进来
 *           UserService
 *   02 需要把 通用代码的 类传入进来
 *          LogUtils
 *
 *   03 创建动态代理对象
 *
 *
 */
public class JdkProxyHandler {

    private UserService userService;

    private LogUtils logUtils;

    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    public void setLogUtils(LogUtils logUtils) {
        this.logUtils = logUtils;
    }

    /**
     * 通过 jvm 给我们创建一个动态代理对象
     * @return
     */
    public Object getProxyObj(){

        //通过反射类型 Proxy 创建动态代理对象

        // 动态代理对象 是 代理类的一个实例 (UserService的实例)
        //需要3个参数:
        /**
         *  1. 类型加载器
         *  2.  获取接口
         *  3.  调用处理对象,需要实现 InvocationHandler接口
         *
         *  代理接口之一的代理实例上的方法调用将被分派到实例调用处理程序的invoke方法，
         *
         */
       Object proxy = Proxy.newProxyInstance(
                userService.getClass().getClassLoader(),
                userService.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                        //这里可以进行代码增强 (通用的代码写到这里 (日志/事务) )
                        logUtils.log();

                        //通过反射调用 userService 的具体方法

                        Object obj = method.invoke(userService,args);

                        logUtils.log();


                        return obj;
                    }
                }
        );

       return proxy;
    }
}
